

-- 给一个node添加底层遮罩，避免其下的视图组件被点击
-- 添加触摸遮罩
function addTouchMask(node,isFullScreen,nOpacity,nZOrder,onClickOutside,onClickAll,swallowTouch)
    local touchMaskId = 1
	nOpacity = nOpacity or 0
	local isTouchBeganOutside = false
    -- 判断世界坐标系的点worldPoint是否处于node内部。
    local function isContain(node,worldPoint)
	    local ptNode = node:convertToNodeSpace(worldPoint)
	    local rectNode = node:getBoundingBox()
	    ptNode = cc.pAdd(ptNode,cc.p(rectNode.width / 2,rectNode.height / 2))
	    local box = node:getBoundingBox()
	    box.x = 0
	    box.y = 0
	    return cc.rectContainsPoint(box,ptNode)
    end

	local function onTouchBegan(touch,event)
		if node:isVisible()and event:getCurrentTarget():isVisible()then	
			if isFullScreen and not isContain(node,touch:getLocation())then
				isTouchBeganOutside = true
			end
			return isFullScreen or isContain(node,touch:getLocation())
		end
		return false
	end
	local function onTouchMoved(touch,event)
		if node:isVisible()and event:getCurrentTarget():isVisible()then	
			return isFullScreen or isContain(node,touch:getLocation())
		end
		return false
	end
	local function onTouchEnded(touch,event)
		if node:isVisible()and event:getCurrentTarget():isVisible()then	
			if isFullScreen and isTouchBeganOutside and nil ~= onClickOutside and not isContain(node,touch:getLocation())then
				onClickOutside(node)				
			end
			if nil ~= onClickAll then
				onClickAll(node)
			end
			return isFullScreen or isContain(node,touch:getLocation())
		end
		return false
	end
	local nodeMask = cc.LayerColor:create()
    local listener = cc.EventListenerTouchOneByOne:create() 
 
    swallowTouch =(swallowTouch == nil and true)or swallowTouch
    listener:setSwallowTouches(swallowTouch)
    listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN) 
    listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED)
    listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED)
    local szMaskSize = node:getContentSize()
    if isFullScreen then
    	szMaskSize = WIDE_SCREEN_SIZE
    end
    nodeMask:setContentSize(szMaskSize)
    nodeMask:setColor(cc.c3b(0,0,0)) 
    nodeMask:setOpacity(nOpacity) 
    nodeMask:setContentSize(szMaskSize)
    nodeMask:ignoreAnchorPointForPosition(false)
    nodeMask:setAnchorPoint(0.5,0.5)
    node:addChild(nodeMask,nZOrder or 0)
    nodeMask:setName("TouchMask_"..touchMaskId)
    touchMaskId = touchMaskId + 1
    nodeMask:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener,nodeMask) 
    return nodeMask
end

-- 延迟执行函数
--todo zjb 相关部分要重构的重构掉 2015年6月10日
function doDelay(nDelay,callback,onCancel) 
    assert(callback)
	local schedule_id = nil
	local scheduler = cc.Director:getInstance():getScheduler()
    local function removeID()
		if schedule_id ~= nil then
			scheduler:unscheduleScriptEntry(schedule_id)
			schedule_id = nil
		end
    end

	local function doNow()
		if schedule_id ~= nil then
            removeID()
            callback()
        end
	end
	schedule_id = scheduler:scheduleScriptFunc(doNow,nDelay,false)
    local function cancel()
		if schedule_id ~= nil then
            removeID()
            if onCancel then
                onCancel()
            end
        end
    end 
    return cancel,doNow
end 
function regNodeEvent(node,fun)
	assert(node)
	assert(fun) 
	local tag='userevt'
	--如果节点还没有被注册过事件，那么就注册事件，并创建事件监听列表
	--如果已经注册过监听事件的话，就直接添加到列表结尾
	if not node[tag] then  
		local function onNodeEvent(event) 
			for key,value in pairs(node[tag]) do 
				value(event)
			end   
		end 
		node:registerScriptHandler(onNodeEvent)
		node[tag]={fun}
		return
	end 
	for key,value in pairs(node[tag]) do 
		if fun == value then 
			return
		end
	end
	table.insert(node[tag],fun)
end 
 






















-------------------------------------------------------------------
-- 							遮罩公共用方法
-------------------------------------------------------------------
-- 给sprite添加遮罩
function maskSprite(cobjSprite,sMaskPng)
	local cobjMask = cc.Sprite:createWithSpriteFrameName(sMaskPng)
	local sizeSprite = cobjSprite:getContentSize()
	local sizeMask = cobjMask:getContentSize()
	local renderTexture = cc.RenderTexture:create(sizeMask.width,sizeMask.height)

	cobjMask:setPosition(cc.p(sizeMask.width / 2,sizeMask.height / 2))
	cobjSprite:setPosition(cc.p(sizeMask.width / 2,sizeMask.height / 2))
	cobjMask:setFlippedY(true)
	cobjSprite:setFlippedY(true)
	cobjSprite:setScaleX(sizeMask.width / sizeSprite.width)
	cobjSprite:setScaleY(sizeMask.height / sizeSprite.height)

	cobjMask:setBlendFunc({src=gl.ONE,dst=gl.ZERO})
	cobjSprite:setBlendFunc({src=gl.DST_ALPHA,dst=gl.ZERO})
	renderTexture:begin()
	cobjMask:visit()
	cobjSprite:visit()
	renderTexture:endToLua()
	local maskedSprite = cc.Sprite:createWithTexture(renderTexture:getSprite():getTexture())
	return maskedSprite
end

-- 给sprite添加菱形遮罩，用于玩家头像
function getDiamondMaskedSprite(cobjSprite)
	return maskSprite(cobjSprite,"res/main/img_portrait_frame1.png")
end


-- 添加灵魂石遮罩,返回SpriteFrame
function maskSoul80X80(nItemID)
	local sPath = string.format("res/props/item_%d.png",nItemID)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("PackageViewCell:setIcon","缺少灵魂石图标资源:"..sPath)
    	sPath = string.format("res/props/item_%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	return maskSprite(cobjSprite,"res/public/img_mask_soul.png"):getSpriteFrame()
end

-- 添加物品遮罩,返回SpriteFrame
function maskItem80X80(nItemID)
	local sPath = string.format("res/props/item_%d.png",nItemID)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("PackageViewCell:setIcon","缺少物品图标资源:"..sPath)
    	sPath = string.format("res/props/item_%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	return maskSprite(cobjSprite,"res/public/img_mask_item.png"):getSpriteFrame()
end

-- 添加英雄头像遮罩,返回SpriteFrame
function maskHero100X100(nHeroID)
	local sPath = string.format("res/portrait/%d.png",nHeroID)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("PackageViewCell:setIcon","缺少英雄图标资源:"..sPath)
    	sPath = string.format("res/portrait/%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	return maskSprite(cobjSprite,"res/public/img_mask_hero.png"):getSpriteFrame()
end

function maskHero155X58(nHeroID)
	local sPath = string.format("res/portrait1/%d.png",nHeroID)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	log.error("PackageViewCell:setIcon","缺少英雄图标资源:"..sPath)
    	sPath = string.format("res/portrait1/%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	return maskSprite(cobjSprite,"res/public/img_mask_herolist.png"):getSpriteFrame()
end

function maskPlayer155X58(nHeroID)
	local sPath = string.format("res/portrait1/%d.png",nHeroID)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("PackageViewCell:setIcon","缺少英雄图标资源:"..sPath)
    	sPath = string.format("res/portrait1/%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	return maskSprite(cobjSprite,"res/public/img_mask_player.png"):getSpriteFrame()
end



-- 添加技能图标遮罩,返回SpriteFrame
function maskSkill_80X80(n_imgId)
	local sPath = string.format("res/skill/%d.png",n_imgId)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("PackageViewCell:setIcon","缺少 技能 图标资源:"..sPath)
    	sPath = string.format("res/props/item_%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	return maskSprite(cobjSprite,"res/public/img_mask_item.png"):getSpriteFrame()
end


-- 添加任务图标遮罩,返回SpriteFrame
function maskTask_80X80(n_imgId)
	local sPath = string.format("res/task/img_%d.png",n_imgId)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("PackageViewCell:setIcon","缺少 技能 图标资源:"..sPath)
    	sPath = string.format("res/props/item_%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	return maskSprite(cobjSprite,"res/public/img_mask_item.png"):getSpriteFrame()
end

-- 添加点金手图标遮罩,返回SpriteFrame
function maskTask_80X81(n_imgId)
	local sPath = string.format("res/midas/img_%d.png",n_imgId)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("PackageViewCell:setIcon","缺少 技能 图标资源:"..sPath)
    	sPath = string.format("res/props/item_%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	return maskSprite(cobjSprite,"res/public/img_mask_item.png"):getSpriteFrame()
end



-- 添加圆形英雄头像遮罩,返回SpriteFrame
function maskHeroCircle(n_imgId,sMaskPng)
	local sPath = string.format("res/portrait/%d.png",n_imgId)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("maskHeroCircle_","缺少 英雄头像 图标资源:"..sPath)
    	sPath = string.format("res/portrait/%d.png",9999)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	sMaskPng = sMaskPng or "res/public/frame/img_mask_hero_133.png"
	 return maskSprite(cobjSprite,sMaskPng):getSpriteFrame()
	-- return maskSprite(cobjSprite,"res/public/img_mask_item.png"):getSpriteFrame()
end

function replaceWithHeroCircle(sprite,n_imgId ,bFlipX)
	sprite:removeAllChildren()
	sprite:setSpriteFrame("res/public/frame/img_mask_hero_bg.png")
	--sprite:setScale(1)
	local child = cc.Sprite:createWithSpriteFrame(maskHeroCircle(n_imgId,"res/public/frame/img_mask_hero_80.png"))
    if bFlipX then
        child:setFlipX(bFlipX)
    end
	local size =sprite:getContentSize()	
	sprite:getTexture():setAntiAliasTexParameters()
	child:getTexture():setAntiAliasTexParameters()
	child:setPosition(cc.p(size.width/2,size.height/2))
	sprite:addChild(child)
	return sprite,child
end 

-- 添加圆形怪物头像遮罩,返回SpriteFrame
function maskMonsterCircle(n_imgId,n_size)
	n_size = n_size or 80
	local sPath = string.format("res/portrait/%d.png",n_imgId)
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
    	--log.error("maskHeroCircle_","缺少 英雄头像 图标资源:"..sPath)
    	sPath = string.format("res/portrait/%d.png",1005)
	end
	local cobjSprite = cc.Sprite:createWithSpriteFrameName(sPath)
	 return maskSprite(cobjSprite,string.format("res/public/frame/img_mask_hero_%d.png",n_size)):getSpriteFrame()
	-- return maskSprite(cobjSprite,"res/public/img_mask_item.png"):getSpriteFrame()
end
function replaceWithMonsterCircle(sprite,n_imgId)
	sprite:removeAllChildren()
	sprite:setSpriteFrame("res/public/frame/img_mask_hero_bg.png")
	sprite:setScale(1)
	local child = cc.Sprite:createWithSpriteFrame(maskMonsterCircle(n_imgId,80))
	local size =sprite:getContentSize()	
	sprite:getTexture():setAntiAliasTexParameters()
	child:getTexture():setAntiAliasTexParameters()
	child:setPosition(cc.p(size.width/2,size.height/2))
	sprite:addChild(child)
	return sprite
end 


function createSkillIcon(nSkillId,bEnabled)
    local node = cc.Node:create()
    local sPath = "res/skill/"..nSkillId..".png"
    local objFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(sPath)
    if nil == objFrame then
        sPath = "res/skill/9999.png"
    end
    local spriteSkill = cc.Sprite:createWithSpriteFrameName(sPath)
    local spriteBg = cc.Sprite:createWithSpriteFrameName("res/public/frame/img_skill_bg.png")
    
    spriteSkill = maskSprite(spriteSkill,"res/public/frame/img_skill_mask.png")
    node:addChild(spriteBg)
    node:addChild(spriteSkill)

    if not bEnabled then
        spriteSkill = Shader.apply(spriteSkill,Shader.SHADER_STONE)
        local lab_locked = TuiManager:getInstance():createLabel(
            0,"",DEFAULT_TTF_PATH,1,22,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0)
        lab_locked:setStyle(1)
        lab_locked:setString(I18N_HERO_SKILL_LOCKED)
        node:addChild(lab_locked)
    end
    --加入尺寸，以便于检查 zjb 2015年7月3日
    node:setContentSize(cc.size(80,80))
    return node
end






-- 验证obj是否为空，为空时调用log.error会打印trace
function checkNil(obj)
	if nil == obj then
		log.error("V","校验对象为空")
	end
	return obj
end

function typeof(var) 
    local _type = type(var)  
    if(_type ~= "table" and _type ~= "userdata")then  
	    return _type  
    end  
    local _meta = getmetatable(var)  
    if(_meta ~= nil and _meta._name ~= nil)then  
        return _meta._name  
    else  
        return _type  
    end  
end

function playSound(id,loop)
    return AudioEngine.playEffect(SoundDataManager:ins():getSoundPath(id),loop)
end  

function stopSound(handler)
    AudioEngine.stopEffect(handler)
end

-- 播放按钮音效
function playButtonEffect()
	playSound(101)
end

-- 重新定义按钮事件，给按钮事件添加声音 SB=SoundButton 不是傻逼的意思
function SB(func)
	return function(...)
		playButtonEffect()
		func(...)
	end
end

-- 根据tag在node极其子node下查找组件
function findChildByTag(node,tag)
    assert(node,"findChildByTag node参数为空！")
    assert(tag,"findChildByTag tag参数为空！")
    
    local function doFind(node,tag)
	    local nodeFound = node:getChildByTag(tag)
	    if nil ~= nodeFound then
		    return nodeFound
	    end
        --修改成ipair遍历数组，速度快于pair zjb 2015年6月5日
	    for _,child in ipairs(node:getChildren())do
		    nodeFound = doFind(child,tag)
		    if nil ~= nodeFound then
			    return nodeFound
		    end
	    end
        return nil
    end
    local result = doFind(node,tag)
    assert(result,'没有找到tag对应的node！')
	return result
end

--批量递归查找tag
--@param node
--@param tagTable tagMap下对应的table
--@param tagTemplate tag名称的模板 写法 PANEL_ITEM_%d
--@param startIndex 起始索引值 默认是1
--@param endIndex 终止索引值 默认是连续最大值
--return 返回找到的对象数组
function findChildrenByTag(node,tagTable,tagTemplate,startIndex,endIndex)
    local i = startIndex or 1
    local result = {}
    while true do
        if endIndex and i>endIndex then break end
        local tagName = string.format(tagTemplate,i)
        if tagTable[tagName] then
            table.insert(result,findChildByTag(node,tagTable[tagName]))
        else
            break
        end
        i = i+1
    end
    return result
end

--function ccGetScheduler()
--	return cc.Director:getInstance():getScheduler()
--end

-- 改变当前node的父节点 解决cell中放panel时点透的问题
function changeParent_deprecated(node,newParent)
	local wpt = node:convertToWorldSpaceAR(cc.p(0,0))
	node:removeFromParent(false)
	node:setPosition(newParent:convertToNodeSpaceAR(wpt))
	newParent:addChild(node)
	return node 
end

--递归打印节点情况
--@param node 根节点
function printChildren(node,depth)
    if node==nil then
        return 
    end
    depth = depth or 0
    result = "\n"
    local function pc(obj,indent,iDepth)
        result = result..indent.."CHILDREN NUM:"..obj:getChildrenCount().."\n"
        for idx,child in ipairs(obj:getChildren())do
            local zOrder = child:getLocalZOrder()
            local visible = child:isVisible()
            local x,y = child:getPosition()
            local str = string.formatI('{}: pos:({},{})ZORDER:{} VISIBLE:{} TAG:{} NAME:{}\n',idx,x,y,zOrder,visible,child:getTag(),child:getName())
            result = result..indent..str
            if iDepth<depth or depth==0 then
                pc(child,indent.."  ",iDepth+1)
            end
	    end
    end
    pc(node,"",1)
    print(result)
end




-- 可将 function(arg1,arg2...)self:method(arg1,arg2,....)的形式简化成h(self,self.method)
--@param selfObj 填self就行
--@param func 要包含的方法，记得用.代替:
function h(selfObj,func)
    return function(...)return func(selfObj,...)end
end

--在一组备选的parent中找到n指定的node处在哪个parent之下，如果不在任何一个之下，返回nil
--@param parents 备选的父容器
--@param node 要查找的node
function findParent(parents,node)
    local set = {}
    for _,l in ipairs(list)do set[l] = true end
    while(true)do
        local parent  = node:getParent()
        if nil == parent then return nil end
        if set[parent] then return parent end
    end 
end

--将一个节点擦脏，在下一帧绘制时会导致该节点重新排序
--@param node
function makeDirty(node)
    local children = node:getChildren()
    if(#children==0)then return end
    local child = children[1]
    local temp = child:getOrderOfArrival()
    node:reorderChild(child,child:getLocalZOrder())
    child:setOrderOfArrival(temp)   
end

function setSamePos(newNode,oldNode)
    local px,py = oldNode:getPosition()
    newNode:setPosition(cc.p(px,py))
end

function cloneNodeParams(srcNode,destNode,bCopyIdentify)
    destNode:setPosition(cc.p(srcNode:getPosition()))
    destNode:setAnchorPoint(srcNode:getAnchorPoint())
    destNode:setLocalZOrder(srcNode:getLocalZOrder())
    destNode:setOrderOfArrival(srcNode:getOrderOfArrival())  
    destNode:setScale(srcNode:getScale())
    if srcNode.isFlippedX and destNode.setFlippedX then
        destNode:setFlippedX(srcNode:isFlippedX())
        destNode:setFlippedY(srcNode:isFlippedY())
    end
    if bCopyIdentify then
        destNode:setTag(srcNode:getTag())
        destNode:setName(srcNode:getName())
    end
end

--替换node
--@param newNode 要加入的node
--@param oldNode 被替换的node
function replaceNode(newNode,oldNode,bCopyIdentify)
    assert(oldNode~=nil and newNode~=nil,'newNode and oldNode must be non-nil!')
    local parent = oldNode:getParent()
    assert(parent~=newNode:getParent(),'newNode must not add to oldNode parent before call replaceNode()!')
    parent:addChild(newNode)
    newNode:setLocalZOrder(oldNode:getLocalZOrder())   
    local temp = newNode:getOrderOfArrival()
    newNode:setOrderOfArrival(oldNode:getOrderOfArrival())  
    oldNode:setOrderOfArrival(temp)
    newNode:setPosition(cc.p(oldNode:getPosition()))
    if bCopyIdentify then
        newNode:setTag(oldNode:getTag())
        newNode:setName(oldNode:getName())
    end    

    oldNode:removeFromParent()
    return
end

--调换两个node的显示次序，确保两个node在一个父对象之下
--@param node1
--@param node2
--@bResort 是否需要重新排序，默认为需要
function swapOrder(node1,node2,bResort)
    local parent = node1:getParent()
    assert(parent==node2:getParent(),'two nodes are not under the same parent!')
    local temp = node1:getLocalZOrder()
    node1:setLocalZOrder(node2:getLocalZOrder())
    node2:setLocalZOrder(temp)
    local tempA = node1:getOrderOfArrival()
    node1:setOrderOfArrival(node2:getOrderOfArrival())
    node2:setOrderOfArrival(tempA)
    if bResort == nil or bResort then
        makeDirty(parent)
    end
end



--在node的前后插入addNode，执行后addNode将会出现在node之前或之后
--@param addNode 要加入的node
--@param node
--@param bBefore true，插入到node的前面，false 插入到node的后面，默认为前面
function insertNode(addNode,node,bBefore)
    local parent = node:getParent()
    if addNode:getParent()~=parent then
        changeParent(addNode,parent)
    else
        makeDirty(parent)
    end
    addNode:setLocalZOrder(node:getLocalZOrder())
    parent:sortAllChildren()
    local nodes = parent:getChildren()
    local nodesL = #nodes
    --1---addNode--2--node--
    --1---node--3---addNode--
    local state = 1
    local tNode = addNode
    for i,child in pairs(nodes)do
        if bBefore == false then
            child = nodes[nodesL+1-i]
        end
        if state == 1 then
            if addNode==child then
                state = 2
            elseif node == child then
                state = 3
            end
        elseif state == 2 then
            swapOrder(addNode,child,false)
            if child == node then
                break
            end
        elseif state == 3 then
            if child==addNode then
                break
            else
                swapOrder(tNode,child,false)
                tNode = child
                state = 3
            end
        end
    end
    -- make dirty
    makeDirty(parent)
end

--将指定节点移动到该父节点最前面的位置
--@param node
function moveToFirst(node)
    local parent = node:getParent()
    local children = parent:getChildren()
    local n = #children
    if n == 1 then return end
    insertNode(node,children[n],true)
end

--将指定节点移动到该父节点最后面的位置
--@param node
function moveToLast(node)
    local parent = node:getParent()
    local children = parent:getChildren()
    local n = #children
    if n == 1 then return end
    insertNode(node,children[1],false)
end

function isParent(node,parent)
    while true do
        node = node:getParent()
        if not node then
            return false
        elseif node==parent then
            return true
        end
    end
end

--改变一个node的父节点对象
--@param node
--@param newParent
--@param changePosition
function changeParent(node,newParent,changePosition)
    local nodeParent = node:getParent()
    if nodeParent==newParent then
        return
    end
    assert(newParent,'新父对象不能为空')
    node:removeFromParent(false)
    newParent:addChild(node)
    if changePosition and nodeParent then
        local px,py = node:getPosition()
        px,py = localPointTo(px,py,nodeParent,newParent)
        node:setPosition(cc.p(px,py))
    end
end


-- 计算字符串规则
-- @param str 待计算的字符串，用{}把表达式括起来，仅支持一层，可以有多个表达式
-- 例如:增加生命值{relic.quality*0.03}。
-- @param params 参数，格式:{ hero = {...},player = { ... },relic = { ... },equip = { ... },skill = { ... } }
--    不需要的参数可以不定义
function evalueString(str,params)
    local nStart,_,str1,str2,str3 = string.find(str,"(.*){(.*)}(.*)")
    if nStart ~= nil then
    	local saved = { player = player,hero = hero,relic = relic,equip = equip,skill = skill }
        player = params.player
        hero = params.hero
        relic = params.relic
        equip = params.equip
        skill = params.skill
        local f = loadstring('return ' .. str2)
        local fvalue = f()
        -- nil连接会出错
        if fvalue==nil then fvalue = '【unknown】' end
        player = saved.player
        hero = saved.hero
        relic = saved.relic
        equip = saved.equip
        skill = saved.skill
        return evalueString(str1,params).. fvalue .. evalueString(str3,params)
    end
    return str
end

--在开发模式下这个值是从本地配置中读取出来的，不在这里配置
DEBUG_DRAW_RECT_ONSCREEN = DEBUG_VERSION

function drawRectOnScreen(x,y,width,height,color,linewidth)
    if not DEBUG_DRAW_RECT_ONSCREEN then
        return
    end
    color = color or 0xffffffff
    linewidth = linewidth or 2
    local rnode = createRectNode(width,height,color,linewidth,color,false,true)
    rnode:setName('rect node')
    --todo 如果在屏幕外的部分，显示信息
    debug_showOnScreen(rnode,x,y)
--    local aa = cc.Sprite:createWithSpriteFrameName("res/public/img_place.png")
--    SceneManager:ins():getScene():addChild(aa)
end


_showTextTasks = {}
_showTextRunning = {}
_showTextLabelCache = {}
function showTextOnScreen(text,x,y)
    if not DEBUG_VERSION then
        return
    end
    local winSize = cc.Director:getInstance():getWinSize()
    x = x or(winSize.width/2)
    y = y or(winSize.height/2)
    text = text or ''
    local key = x..':'..y
    if not _showTextTasks[key] then
        _showTextTasks[key] = {}
    end
    local cache = _showTextTasks[key]
    if _showTextRunning[key] then
        table.insert(cache,{text,x,y})
        return
    end
    local function getLabel(text)
        local lb = table.remove(_showTextLabelCache)
        if lb then
            lb:setString(text)
            lb:setOpacity(255)
        else
            lb = cc.Label:createWithTTF({fontFilePath=DEFAULT_TTF_PATH,fontSize=30},text)
            lb:retain()
        end
        lb:setName('show_on_screen_text:'..text)
        return lb
    end
    local function runNext(text,x,y)
        _showTextRunning[key] = true
        local lb = getLabel(text)
        local t = 3
        debug_showOnScreen(lb,x,y,t)
        local px,py = lb:getPosition()
        local startT = getCurrentTime()
        local steps = {{{1.7,'move',{px,py+70}}},{{1,'move',{px,py+100}},{1,'fadeout'}}}
        local maxArr = {}
        local function onFrame()
            local t = getCurrentTime()-startT
            for i,stepAnimes in ipairs(steps)do
                if not maxArr[i] then
                    local maxTime = 0
                    for _,anime in ipairs(stepAnimes)do
                        maxTime = math.max(anime[1],maxTime)
                    end
                    maxArr[i] = maxTime
                end
                local maxTime = maxArr[i]
                if maxTime>=t then
                    --run anime
                    local percent = t/maxTime
                    for _,anime in ipairs(stepAnimes)do
                        local aTime = anime[1]
                        local aType = anime[2]
                        if aType=='move' then
                            local toX,toY = unpack(anime[3])
                            if not anime[4] then
                                local _x,_y = lb:getPosition()
                                anime[4] = {_x,_y}
                            end
                            local fromX,fromY = unpack(anime[4])
                            local pX = fromX+(toX-fromX)*percent
                            local pY = fromY+(toY-fromY)*percent
                            lb:setPosition(cc.p(pX,pY))
                        elseif aType=='fadeout' then
                            lb:setOpacity(255*(1-percent))
                        end
                    end
                    --todo 此处可优化 zjb 2015年6月4日
                    doNextFrame(onFrame)
                    break
                else
                    t=t-maxTime
                end
            end
        end
        onFrame()
--        print(px,py)
--        lb:runAction(cc.Sequence:create({
--                cc.MoveTo:create(1.7,cc.p(px,py+70)),
--                cc.Spawn:create({
--                    cc.MoveTo:create(1,cc.p(px,py+100)),
--                    cc.FadeOut:create(1)}),
--                cc.CallFunc:create(function()

--                end)
--            }))
        doDelay(t,function()
            table.insert(_showTextLabelCache,lb)
        end)
        doDelay(0.7,function()
            if #cache>0 then
                runNext(unpack(table.remove(cache,1)))
            else
                _showTextRunning[key] = false
            end               
        end)

    end

    runNext(text,x,y)
    
end

function getCurrentScene()
    return cc.Director:getInstance():getRunningScene()   
end

function pts(...)-- print text on screen
    if not DEBUG_VERSION then
        return
    end
    local arr = {}
    for i=1,select('#',...)do
        table.insert(arr,_ps(select(i,...)))
    end
    if #arr==1 then
        text = arr[1]
    elseif #arr==0 then
        text = '__NO__TEXT__'
    else
        text = table.concat(arr,',')
    end
    print(text)
    showTextOnScreen(text)
    
end

function showNodeRectOnScreen(node)
    if not DEBUG_VERSION then
        return
    end
    local bb = getNodeBoundRectOnScreen(node)
    print(bb.x,bb.y,bb.width,bb.height)
    drawRectOnScreen(bb.x,bb.y,bb.width,bb.height)
end


function getTopDebugLayer()
    if not _top_debug_layer then
        local tdl = cc.LayerColor:create()
        _top_debug_layer = tdl
        tdl:retain()
        tdl:setName('_top_debug_layer')
        --tdl:addChild(createRectNode(100,100,0x80ffffff))
        local scene = getCurrentScene()
        if scene then
            scene:addChild(tdl)
        else
            doNextFrame(function()
                getCurrentScene():addChild(tdl)
            end)
        end
        local function check()
            local scene = getCurrentScene()
            if scene and scene~=tdl:getParent()then
                changeParent(tdl,scene)
            end
            if scene then
                moveToFirst(tdl)
            end
            doNextFrame(check)
        end
        check()
    end
    return _top_debug_layer
end

function debug_showOnScreen(node,x,y,delay)
    assert(node)
    x = x or 0
    y = y or 0
    delay = delay or 1
    local scene = getTopDebugLayer()
    local p = scene:convertToWorldSpace(cc.p(0,0))
    scene:addChild(node)
    node:setPosition(cc.p(x-p.x,y-p.y))
    node:setLocalZOrder(1000000)
    doDelay(delay,function()
        node:removeFromParent()
    end)
    return rnode
end



--[Comment]
--原理说明：该方法用getBoundingBox判断一个点是否在node内
--boundingBox只与1.node的contentsize,2.在父节点的位置相关，
--与node本身实际所放的内容无关,与内容所处的位置无关，与父节点的contentsize和子节点的contentsize都无关
--contentsize是一个纯手动维护的值
--注意：为了确保结果的正确，选取的node应该是
--1.内容大体是矩形
--2.矩形在node内处于中心位置
--3.ContentSize有正确的设置
function isInNodeRect(node,worldPoint)
    local bb = getNodeBoundRectOnScreen(node)
    drawRectOnScreen(bb.x,bb.y,bb.width,bb.height)
    local x,y = getNodePositionOnScreen(node)
    drawRectOnScreen(x,y,1,1,0xffff0000,1)
    return cc.rectContainsPoint(bb,worldPoint)
end

function getNodePositionOnScreen(node)
    local worldBBPoint = node:convertToWorldSpace(cc.p(0,0))
    return worldBBPoint.x,worldBBPoint.y
end

function getNodeBoundRectOnScreen(node)
    local bb = node:getBoundingBox()
    local worldBBPoint = node:convertToWorldSpace(cc.p(0,0))
    bb.x = worldBBPoint.x
    bb.y = worldBBPoint.y
    if(node:isIgnoreAnchorPointForPosition()) then
        bb.x = bb.x -0.5*bb.width
        bb.y = bb.y -0.5*bb.height
    else
        local ap = node:getAnchorPoint()
        pp(ap)
        bb.x = bb.x - (0.5-ap.x)*bb.width
        bb.y = bb.y - (0.5-ap.y)*bb.height
    end
    return bb
end


--[Comment]
--对任意对象添加点击功能
--@param node 点击对象
--@param onClick 点击时的回调，回调函数回传node本身
--@param animated 是否需要动画效果 默认为是
--@param checkBoundFunc 检查node边界的方法，不提供默认采用isInNodeRect
--@param checkNode 用于检测的对象和回调的对象有可能不是同一个对象，如果不是的时候，用这个参数指明
function addClick(operationName,node,onClick,animated,checkBoundFunc,checkNode,bSwallow,noSound,isCheckTime)
    assert(operationName,'must have operationName')
    if node._ADDCLICK_REMOVE then
        node._ADDCLICK_REMOVE()
    end
    if not onClick then
        return
    end
    local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
    local clickedTime = nil

    checkBoundFunc = checkBoundFunc or isInNodeRect
    checkNode = checkNode or node
    local listener = cc.EventListenerTouchOneByOne:create()
    animated = animated == nil or animated
    if animated and node.setSyncScaleParent then
        node:setSyncScaleParent(true)
    end
    if bSwallow == nil then
        bSwallow = false
    end
    if isCheckTime == nil then
        isCheckTime = true
    end
    listener:setSwallowTouches(bSwallow)
    listener:registerScriptHandler(function(touch,event)
	    local p=node 
		while(p)do 
			if not p:isVisible() then
				return false
			end 
			p=p:getParent()
		end
        local result = checkBoundFunc(checkNode,touch:getLocation())
        if result then
            if animated then
                node:runAction(cc.ScaleTo:create(0.1,0.9))
            end
            if not noSound then
                playSound(101)
            end
        end
        return result
    end,cc.Handler.EVENT_TOUCH_BEGAN) 
    listener:registerScriptHandler(function(touch,event)
        if animated then
            node:runAction(cc.ScaleTo:create(0.1,0.9))
        end
        return true
    end ,cc.Handler.EVENT_TOUCH_MOVED)
    listener:registerScriptHandler(function(touch,event)
        local tp = touch:getLocation() 
        local function doClick()  
            if checkBoundFunc(checkNode,tp)then
                clickedTime = getCurrentTime()
                userop.userop(operationName)
                onClick(node)
            end
        end
        if animated then
		    --这边要加个防止重复点击保护
		    local dlg = ModalDlgManager.createDlg();
		    cc.Director:getInstance():getRunningScene():addChild(dlg,109999);
            node:runAction(cc.Sequence:create(
                cc.ScaleTo:create(0.1,1),
                cc.CallFunc:create(function() doClick();
				dlg:removeFromParent();
				end)
			))
        else
            doClick()
        end
        
        return true
    end ,cc.Handler.EVENT_TOUCH_ENDED) 
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener,node)
    local exited = false
    
    local delClick
    local onScriptHandler
    delClick = function()
        node._ADDCLICK_REMOVE = nil
        eventDispatcher:removeEventListener(listener)
        node:unregisterScriptHandler(onScriptHandler)
    end
    onScriptHandler = function(event)
        if event == 'enter' and exited then
            addClick(operationName,node,onClick,animated,checkBoundFunc,checkNode)
        elseif event == 'exit' then
            exited = true
        elseif event == 'cleanup' then
            delClick()
        end
    end
    node._ADDCLICK_REMOVE = delClick
    enableNodeMultipleScriptHandler(node)
    node:registerScriptHandler(onScriptHandler)

end

function delClick(node)
    addClick('',node)
end


--[Comment]
--对cell容器添加点击cell功能
--@param view 要添加的对象
--@param onClick 点击时的回调，回调函数回传node本身
--@param animated 是否需要动画效果 默认为是
--@param checkBoundFunc 检查cell边界的方法，不提供采用默认的方法isInNodeRect
function addClickToCell(operationName,view,onClick,animated,checkBoundFunc)
    assert(operationName,'must have operationName')
    local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
    if view._ADDCLICK_LISTENER then
        eventDispatcher:removeEventListener(view._ADDCLICK_LISTENER)
    end
    
    checkBoundFunc = checkBoundFunc or isInNodeRect
    local listener = cc.EventListenerTouchOneByOne:create()
    local node = nil
    local checkNode = nil
    view._ADDCLICK_LISTENER = listener
    if animated == nil then
        animated = true
    end
    listener:registerScriptHandler(function(touch,event)
		node=view
		while(node)do  
			if not node:isVisible() then  
				return false
			end
			node=node:getParent()
		end
        local tp = touch:getLocation()
        if not isInNodeRect(view,tp)then
            return false
        end
        local cells = view:getCells()
        for _,cell in ipairs(cells)do
            --不应该这么写，有漏洞 zjb 2015年7月23日
            local firstNode = cell:getChildren()[1]
            if checkBoundFunc(firstNode,tp)then
                node = cell
                checkNode = firstNode
                if animated then
                    checkNode:runAction(cc.ScaleTo:create(0.1,0.9))
                end
                return true
            end
        end
        return false
    end,cc.Handler.EVENT_TOUCH_BEGAN) 
    listener:registerScriptHandler(function(touch,event)
        if animated then
            checkNode:runAction(cc.ScaleTo:create(0.1,0.9))
        end
        return true
    end ,cc.Handler.EVENT_TOUCH_MOVED)
    listener:registerScriptHandler(function(touch,event)
        local tp = touch:getLocation()
        local node_temp,checkNode_temp = node,checkNode
        local scrolled = view:isScrolled()
        local function doClick()
            if(not scrolled)and checkBoundFunc(checkNode_temp,tp)then
                userop.userop(operationName)
                onClick(node_temp)
            end
        end
        -- checkNode 有可能在多次触摸时为空，因此做一个条件检查，但具体原因要做测试跟踪 zjb 2015年7月21日
        if animated and checkNode_temp then

            local dlg = ModalDlgManager.createDlg();
            cc.Director:getInstance():getRunningScene():addChild(dlg,109999);
            checkNode_temp:runAction(cc.Sequence:create(
                cc.ScaleTo:create(0.1,1),
                cc.CallFunc:create(function() doClick();
                dlg:removeFromParent();
                end)
            ))

        else
            doClick()
        end
        node = nil
        checkNode = nil
        return true
    end ,cc.Handler.EVENT_TOUCH_ENDED) 
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener,view)       
end

function isInScrollView(scrollObj,worldPoint)
    local bb = scrollObj:getBoundingBox()
    local worldBBPoint = scrollObj:getParent():convertToWorldSpace(cc.p(bb.x,bb.y))
    bb.x = worldBBPoint.x
    bb.y = worldBBPoint.y
    drawRectOnScreen(bb.x,bb.y,bb.width,bb.height,0xffff0000)
    return cc.rectContainsPoint(bb,worldPoint)
end

--[Comment]
--防止超出滚动面板可视区域之外的部分响应点击
--@param scrollObj 滚动对象
function preventOutsideTouch(scrollObj)
    local node = cc.Node:create()-- 需要一个节点确保该节点的点击会在所有的容器内容之前触发
    scrollObj:addChild(node)
    local listener = cc.EventListenerTouchOneByOne:create()
    local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
    listener:registerScriptHandler(function(touch,event)
        if(not isInScrollView(scrollObj,touch:getLocation()))then
            eventDispatcher:pauseEventListenersForTarget(scrollObj:getContainer(),true)
        else
            eventDispatcher:resumeEventListenersForTarget(scrollObj:getContainer(),true)
        end
        return true
    end,cc.Handler.EVENT_TOUCH_BEGAN) 
    listener:registerScriptHandler(function(touch,event)
        return true
    end ,cc.Handler.EVENT_TOUCH_MOVED)
    listener:registerScriptHandler(function(touch,event)
        return true
    end ,cc.Handler.EVENT_TOUCH_ENDED)
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener,node)
end

--[Comment]
--todo 移动到LuaExtendModule模块
function arrayConcat(t1,t2)
    for i=1,#t2 do
        t1[#t1+1] = t2[i]
    end
    --上一种方法比下一种方法要快%3左右，因为rehash的次数更少
    --[[
    for _,v in ipairs(t2)do
        table.insert(t1,v)
    end]]
    return t1
end




--[Comment]
--生成一个矩形单色node
-- @param w 矩形的宽度
-- @param h 矩形的高度
-- @param color 矩形的颜色：用0xAARRGGBB 的整数表示
-- @param border 边框宽度，默认为0
-- @param borderColor 边框颜色
-- @param isCenter 如果为true，则以0,0点为中心画矩形，否则以(w/2,h/2)为中心画矩形
-- @param hollow 是否为空心，默认为实心
function createRectNode(w,h,color,border,borderColor,isCenter,hollow)
	if color == nil then color = 0xffffffff end
    if hollow == nil then hollow = false end
    local node = cc.DrawNode:create()
    local ox = 0
    local oy = 0
    if isCenter then
        ox = -w/2
        oy = -h/2
    end
    local a,r,g,b = getARGB(color)
    color = cc.c4f(r,g,b,a)
    local vList = {cc.p(ox,oy),cc.p(ox,h+oy),cc.p(w+ox,h+oy),cc.p(w+ox,oy)}
    if hollow then
        border = border or 1
        table.insert(vList,vList[1])
        for i = 1,4 do
            node:drawSegment(vList[i],vList[i+1],border,color)
        end
    else
        
        if border == nil then
            border = 0
        end
        local a2,r2,g2,b2 = 0,0,0,0
        if borderColor == nil then
            borderColor = 0xffffffff
        end
        a2,r2,g2,b2 = getARGB(borderColor)
        node:drawPolygon(vList,4,color,border,cc.c4f(r2,g2,b2,a2))
    end
    node:setContentSize(cc.size(w,h))
	return node
end

function getQualityColor(quality)
    if QUALITY_I_COLOR[quality] then
        return getC4b(QUALITY_I_COLOR[quality])
    else
        return COLOR_BLACK
        --assert(false,'null quality '..quality)
    end
end

--[Comment]
--将一个0xAARRGGBB的数字转换成cc.c4b结构
function getC4b(iColor)
    local a,r,g,b = getARGB(iColor)
    return cc.c4b(r*255,g*255,b*255,a*255)
end

--[Comment]
-- 将0xAARRGGBB的数字分解成值在0~1之间的(r,g,b,a)值
function getARGB(iColor)
    local b = iColor%0x100
	iColor = iColor-b
	local g = iColor%0x10000
	iColor = iColor-g
	local r = iColor%0x1000000
	iColor = iColor-r
	local a = iColor%0x100000000
	a = a/0xff000000
	r = r/0xff0000
	g = g/0xff00
	b = b/0xff    
    return a,r,g,b
end

--[Comment]
-- 将0xRRGGBB的数字分解成值在0~1之间的(r,g,b)值
function getRGB(iColor)
    local b = iColor%0x100
	iColor = iColor-b
	local g = iColor%0x10000
	iColor = iColor-g
	local r = iColor%0x1000000
	r = r/0xff0000
	g = g/0xff00
	b = b/0xff    
    return r,g,b
end


dicLazy  = {}
--[Comment]
-- 使得点击在多少毫秒内不能连续响应
function lazyClick(funcClick,nLazy)
    nLazy = nLazy or 0.5
    if dicLazy[funcClick] == nil then 
        funcClick()
        dicLazy[funcClick] = nLazy
        doDelay(nLazy,function()
             dicLazy[funcClick] = nil 
        end)
    end
end

--[Comment]
-- 显示旋转效果 获得装备、英雄升级、英雄升星、战斗胜利等界面循环旋转的效果 传入参数为站位的对象
function showCycleRotationEffect(imgPlace)
--[[
    local animation = sp.SkeletonAnimation:createWithFile(EFFECT_CYCLE_ROTATION_JSON_PATH,EFFECT_CYCLE_ROTATION_ATLAS_PATH,1)
    animation:setAnimation(0,"xuanzhuanquan",true)
    animation:setPosition(cc.p(imgPlace:getContentSize().width/2,imgPlace:getContentSize().height/2))
    --animation:setPosition(cc.p(imgPlace:getPosition()))
    --animation:setLocalZOrder(imgPlace:getLocalZOrder())    
    --imgPlace:getParent():addChild(animation)
    --imgPlace:removeFromParent()
    imgPlace:addChild(animation)
    return animation
--]]
    local repeatAction = cc.RepeatForever:create(cc.RotateBy:create(0.5,60)) 
    imgPlace:runAction(repeatAction) 
end

--[Comment]
-- 添加纹理
function addPlist(plist)
	cc.SpriteFrameCache:getInstance():addSpriteFrames(plist)
end 

--[Comment]
-- 删除纹理
function removePlist(plist)
	cc.SpriteFrameCache:getInstance():removeSpriteFramesFromFile(plist) 
	--这个需要继续判断是否移除对应纹理
end

--[Comment]
-- 获取frame
function getFrame(png)
	local frame = cc.SpriteFrameCache:getInstance():getSpriteFrame(png)
	if frame == nil then 
		log.error("getFrame","纹理图片未找到:"..png)
	end
	return frame
end

--[Comment]
-- 将本地坐标转换成世界坐标
function localPointToGlobal(x,y,node)
    return node:convertToWorldSpace(cc.p(x,y))
end

--[Comment]
-- 将世界坐标转换成本地坐标
function globalPointToLocal(x,y,node)
    return node:convertToNodeSpace(cc.p(x,y))
end

--[Comment]
-- 将一个本地坐标转换成另一个本地坐标
--todo zjb 一系列的名字取得不好，重构
function localPointTo(x,y,localNode,anotherNode)
    local p = localNode:convertToWorldSpace(cc.p(x,y))
    local p2 = anotherNode:convertToNodeSpace(p)
    return p2.x,p2.y
end

--[Comment]
-- 从一组node中查找node共同的父对象
function getPublicParent(...)
    local arg = {...}
    local argL = #arg
    if argL==0 then return nil
    else
        local function buildParentList(node)
            local parents = {node}
            -- 构建父列表
            while(true)do
                node = node:getParent()
                if node then
                    table.insert(parents,1,node)
                else
                    break
                end
            end
            return parents
        end
        local parents = buildParentList(arg[1])
        local publicParentIndex = #parents

        
        local i = 2
        while(i<=argL)do
            local pList = buildParentList(arg[i])
            local l = math.max(#pList,#parents)
            local sameI = 0
            for j = 1,l do
                if parents[j]==pList[j] then
                    sameI = j
                else
                    break
                end
            end
            if sameI == 0 then return nil
            elseif sameI<publicParentIndex then
                publicParentIndex = sameI
            end
            i=i+1
        end
        return parents[publicParentIndex]

    end
end

--[Comment]
-- 替换new标识为动画
function replaceNewIconByAnim(img)
	local TAG_ANIM = 1111
	if img:isVisible()and img:getChildByTag(TAG_ANIM)== nil then 
	    local json = "res/main/new.json"
	    local atlas = "res/main/new.atlas"
	    local anim  = sp.SkeletonAnimation:createWithFile(json,atlas,1)
	    anim:setAnimation(0,"end",true)
	    anim:setPosition(cc.p(10,10))		
	    img:addChild(anim,0,TAG_ANIM)
	    img:setSpriteFrame("res/public/img_place.png")
	end	
end



--[Comment]
--在指定的容器的指定的位置播放一个动画，如果动画(nodeName)已经存在，则用旧对象播放,
--nodename如果不设置，则表示不重复用一个动画实例
--如果指定了回调，则会在播放完毕后回调，
--如果指定了删除，则会在播放完毕后删除，（仅当不循环播放时有意义），
function playSpine(nodeName,path,animeName,container,x,y,loopOrCallback,autoRemove)
    assert(path and path~='')
    assert(animeName and animeName~='')
    assert(container)
    x = x or 0
    y = y or 0
    local loop = loopOrCallback==true
    local anim
    if  nodeName then
        anim = container:getChildByName(nodeName) 
    end
    anim = anim or sp.SkeletonAnimation:createWithFile(path..'.json',path..'.atlas')
    changeParent(anim,container)
    if anim._stopPreviousPlaySpine then
        anim._stopPreviousPlaySpine()
    end
    anim:setVisible(true)
    anim:setName(nodeName)
    anim:setAnimation(0,animeName,loop)
    anim:setPosition(cc.p(x,y))
    if loop then
        return function()
            anim:clearTracks()
            anim:setVisible(false)
        end
    else
        local function removeAnim()
            anim:setName(nil)
            doNextFrame(function()
                anim:removeFromParent()
            end)
        end
        anim._stopPreviousPlaySpine = function()
            anim:clearTracks()
            anim:setVisible(false)
            anim:setEndListener(nil)
            anim._stopPreviousPlaySpine = nil
        end
        anim:setEndListener(function(track)
            anim:setEndListener(nil)
            if autoRemove then
                removeAnim()
            end
            if loopOrCallback then
                loopOrCallback()
            end
        end)

        
        local function cancel()
            if anim._stopPreviousPlaySpine then
                anim._stopPreviousPlaySpine()
            end
        end
        local function doNow()
            cancel()
            if loopOrCallback then
                if autoRemove then
                    removeAnim()
                else
                    anim:setVisible(false)
                    anim:clearTracks()
                end
                loopOrCallback()
            end
        end
        return cancel,doNow
    end

end


-- 添加触摸遮罩
function addTouchEvent(node,touchBegin,touchMove,touchEnd)
    node:ignoreAnchorPointForPosition(false)
    local isTouchBeganOutside = false
    local function onTouchBegan(touch,event)
        return touchBegin(touch,event)
    end
    ----
    local function onTouchMoved(touch,event)
        if nil ~= touchMove then
            return touchMove(touch,event)
        end

        return true
    end
    ---- 
    local function onTouchEnded(touch,event)
        if nil ~= touchEnd then
            return touchEnd(touch,event)
        end  
        return true
    end

    local listener = cc.EventListenerTouchOneByOne:create() 
    listener:setSwallowTouches(false)
    listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN) 
    listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED)
    listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED)
    node:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener,node) 
    return node
end

-- 重新载入
function reloadModule(arrPath)
	for _,filename in pairs(arrPath) do
		--卸载旧文件
		package.loaded[filename] = nil
		--加载新文件
     	require(filename)
    end
end



--改变node的registerScriptHandler和unregisterScriptHandler的行为，使这个对像能够处理多个handler
--修改之后，registerScriptHandler不会顶掉之前的handler，unregisterScriptHandler可指定要移除的方法
function enableNodeMultipleScriptHandler(node)
    if (node._MULTIPLESCRIPTHANDLERARR_) then
        return
    end
    --存放function的list
    local listeners
    local function makeListeners()
        listeners = {}
        node._MULTIPLESCRIPTHANDLERARR_ = listeners
    end
    makeListeners()

    node._original_registerScriptHandler = node.registerScriptHandler
    node._original_unregisterScriptHandler = node.unregisterScriptHandler
    --改变行为
    node.registerScriptHandler = function(nodeSelf,func)
        if not table.indexOf(listeners,func) then
            table.insert(listeners,func)
        end
    end
    local isInEventLoop = false
    local deleteFuncs = {}
    local deleteAllFlag = false
    node.unregisterScriptHandler = function(nodeSelf,func)
        if func then
            local index = table.indexOf(listeners,func)
            if index then
                if isInEventLoop then
                    table.remove(listeners,index) 
                else
                    deleteFuncs[func] = true
                end
            end
        else
            --删除所有
            if isInEventLoop then
                makeListeners()
            else
                deleteAllFlag = true
            end
            
        end
    end
    local function fireScriptHandler(event)
        isInEventLoop = true
        for _,func in ipairs(listeners) do
            func(event)
        end
        --处理删除事件
        isInEventLoop = false
        if deleteAllFlag then
            makeListeners()
            deleteAllFlag = false
        else
            for k in pairs(deleteFuncs) do
                local index = table.indexOf(listeners,func)
                deleteFuncs[k] = nil
                if index then
                    table.remove(listeners,index)
                end
            end
        end
        if event == 'cleanup' then
            node:_original_unregisterScriptHandler()
        end
    end
    node:_original_registerScriptHandler(fireScriptHandler)
end


--生成一个模态层
function createModalLayer()
    local layer = cc.Layer:create()
    local touchrect = nil
    local function onTouchBegan(touch, event)
        return true
    end
    local listener = cc.EventListenerTouchOneByOne:create()
    listener:setSwallowTouches(true)
    listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN)
    local eventDispatcher = layer:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener,layer)
    
    local layercolor = cc.LayerColor:create(cc.c3b(0,0,0)) 
    layercolor:setAnchorPoint(cc.p(0,0))
    layercolor:setPosition(cc.p(0,0))
    layer:addChild(layercolor)
    layercolor:setOpacity(150)
    layer.setTouchRect = function(rect)
        touchrect = rect
    end
    return layer
end



--设置全身像
function setFigure(sprite,id)
    id = id or 0
    local path = "res/card_head_role/"..id..".png"
    if not cc.FileUtils:getInstance():isFileExist(path) then 
        path = "res/card_head_role/null.png"
    end
    sprite:setTexture(path)
end



function showSceneAnime(view)
    view:setScale(0.9)
    local s1=cc.ScaleTo:create(0.1,1.1) 
    local s2=cc.ScaleTo:create(0.1,1)  
    view:runAction(cc.Sequence:create(s1,s2))
end

-- 单位转换 
function getCurrencyConverter(nNum)
    local sCurr = ""

    if nNum >= 10000 then
		sCurr = string.format(I18N_MESSAGE_CURRENCY_WAN,math.floor(nNum/10000))
    elseif nNum >= 100000000 then
        sCurr = string.format(I18N_MESSAGE_CURRENCY_YI,math.floor(nNum/100000000))
	else
		sCurr = nNum
	end
    return sCurr
end

function setNameWithBg(ubb,img9,name)
    if name and name~='' then
        ubb:setVisible(true)
        img9:setVisible(true)
        ubb:setString(string.formatI('[center][s,1.8,1.8][7]{}[/7][/s][/center]',name))
        local size = img9:getContentSize()
        size.width = ubb.maxW+50
        img9:setContentSize(size)
    else
        ubb:setVisible(false)
        img9:setVisible(false)
    end
end



function getCurrentTime()
    if not _socket_getCurrentTime then
        _socket_getCurrentTime = require 'socket'
    end
    return _socket_getCurrentTime.gettime()
end